/**
 * @file xmc_dac.h
 * @date 2015-08-31
 *
 * @cond
 **********************************************************************************
 * XMClib v2.1.18 - XMC Peripheral Driver Library 
 *
 * Copyright (c) 2015-2018, Infineon Technologies AG
 * All rights reserved.                        
 *                                             
 * Redistribution and use in source and binary forms, with or without           
 * modification,are permitted provided that the following conditions are met:   
 *                                                                              
 *   Redistributions of source code must retain the above copyright notice,      
 *   this list of conditions and the following disclaimer.                        
 * 
 *   Redistributions in binary form must reproduce the above copyright notice,   
 *   this list of conditions and the following disclaimer in the documentation    
 *   and/or other materials provided with the distribution.                       
 * 
 *   Neither the name of the copyright holders nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software without
 *   specific prior written permission.                                           
 *                                                                              
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE    
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE   
 * ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE   
 * LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR         
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF         
 * SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN      
 * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)       
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE   
 * POSSIBILITY OF SUCH DAMAGE.                                                  
 *                                                                              
 * To improve the quality of the software, users are encouraged to share        
 * modifications, enhancements or bug fixes with Infineon Technologies AG       
 * dave@infineon.com).                                                          
 **********************************************************************************
 *
 * Change History
 * --------------
 *
 * 2015-02-18:
 *     - Initial version
 *      
 * 2015-02-20:
 *     - Driver description added
 *
 * 2015-06-19:
 *     - Removed version macros and declaration of GetDriverVersion API
 *
 * 2015-08-31:
 *     - Help document updated
 * @endcond 
 *
 */

#ifndef XMC_DAC_H
#define XMC_DAC_H

/*******************************************************************************
 * HEADER FILES
 *******************************************************************************/

#include <xmc_common.h>

/* DAC peripheral is not available on XMC1X devices. */
#if defined(DAC)

/**
 * @addtogroup XMClib
 * @{
 */

/**
 * @addtogroup DAC
 * @{
 *
 * @brief Digital to Analog Converter (DAC) driver for XMC 4000 microcontroller family. <br>
 *
 * DAC driver uses DAC peripheral to convert digital value to analog value. XMC4000 microcontroller family has two DAC channels of 12-bit resolution
 * and maximum conversion rate of 2MHz with full accuracy and 5MHz with reduced accuracy.
 * It consists of inbuilt pattern generator, ramp generator and noise generator modes. Additionally, waveforms can be generated by configuring data registers
 * in single value mode and in data mode.
 * It has DMA handling capability to generate custom waveforms in data mode without CPU intervention.
 *
 * DAC driver features:
 * -#  Configuration structure XMC_DAC_CH_CONFIG_t and initialization function XMC_DAC_CH_Init() to initialize DAC and configure channel settings
 * -#  Pattern Generator Mode:
 * 	- DAC is configured in pattern generator mode using XMC_DAC_CH_StartPatternMode()
 * 	- XMC_DAC_CH_SetPattern() is used to set the waveform pattern values in pattern register for one quarter
 * 	- Allows to change the trigger frequency using XMC_DAC_CH_SetPatternFrequency()
 * -#  Single Value Mode:
 * 	- DAC is configured in single value mode using XMC_DAC_CH_StartSingleValueMode()
 * 	- Allows to change the trigger frequency using XMC_DAC_CH_SetFrequency()
 * -# Data Mode:
 * 	- DAC is configured in data mode using XMC_DAC_CH_StartDataMode()
 * 	- Allows to change the trigger frequency using XMC_DAC_CH_SetFrequency()
 * -# Ramp Mode:
 *  - DAC is configured in ramp generator mode using XMC_DAC_CH_StartRampMode()
 *  - Allows to change the trigger frequency using XMC_DAC_CH_SetRampFrequency()
 *  - Allows to set the start and stop values of the ramp using XMC_DAC_CH_SetRampStart() and XMC_DAC_CH_SetRampStop()
 * -# Noise Mode:
 * 	- DAC is configured in noise mode using XMC_DAC_CH_StartNoiseMode()
 * 	- Allows to change the trigger frequency using XMC_DAC_CH_SetFrequency()
 * -# Allows to change the scale, offset dynamically using XMC_DAC_CH_SetOutputScale() and XMC_DAC_CH_SetOutputOffset() respectively
 * -# Allows to select one of the eight possible trigger sources using XMC_DAC_CH_SetTrigger()
 * -# 2 DAC channels can be used in synchronization in single value mode and data mode to generate two analog outputs in sync. XMC_DAC_EnableSimultaneousDataMode()
 */

/*******************************************************************************
 * MACROS
 *******************************************************************************/

#define XMC_DAC0 ((XMC_DAC_t *)DAC_BASE)         /**< DAC module register base */

#define XMC_DAC_DACCFG_NEGATE_Msk (0x10000000UL) /*< DAC negation enable mask in XMC44 device */
#define XMC_DAC_NO_CHANNELS (2U)                 /**< DAC maximum channels */
#define XMC_DAC_SAMPLES_PER_PERIOD (32U)         /**< DAC samples per period in pattern mode */

#define XMC_DAC_PATTERN_TRIANGLE  {0U, 4U, 8U, 12U, 16U, 19U, 23U, 27U, 31U} /**< First quarter Triangle waveform samples */ 
#define XMC_DAC_PATTERN_SINE      {0U, 6U, 12U, 17U, 22U, 26U, 29U, 30U, 31U} /**< First quarter Sine waveform samples */
#define XMC_DAC_PATTERN_RECTANGLE {31U, 31U, 31U, 31U, 31U, 31U, 31U, 31U, 31U} /**< First quarter Rectangle waveform samples */

#define XMC_DAC_IS_DAC_VALID(PTR)            ((PTR) == XMC_DAC0)
#define XMC_DAC_IS_CHANNEL_VALID(CH)         (CH < XMC_DAC_NO_CHANNELS)
#define XMC_DAC_IS_TRIGGER_VALID(TRIGGER)    ((TRIGGER == XMC_DAC_CH_TRIGGER_INTERNAL) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_CCU80_SR1) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_CCU40_SR1) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_CCU41_SR1) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_P2_9) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_P2_8) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_U0C0_DX1INS) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_EXTERNAL_U1C0_DX1INS) ||\
                                              (TRIGGER == XMC_DAC_CH_TRIGGER_SOFTWARE))
#define XMC_DAC_IS_MODE_VALID(MODE)          ((MODE == XMC_DAC_CH_MODE_IDLE) ||\
                                              (MODE == XMC_DAC_CH_MODE_SINGLE) ||\
                                              (MODE == XMC_DAC_CH_MODE_DATA) ||\
                                              (MODE == XMC_DAC_CH_MODE_PATTERN) ||\
                                              (MODE == XMC_DAC_CH_MODE_NOISE) ||\
                                              (MODE == XMC_DAC_CH_MODE_RAMP))
#define XMC_DAC_IS_OUTPUT_SCALE_VALID(SCALE) ((SCALE == XMC_DAC_CH_OUTPUT_SCALE_NONE) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_2) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_4) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_8) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_16) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_32) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_64) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_MUL_128) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_2) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_4) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_8) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_16) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_32) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_64) ||\
                                              (SCALE == XMC_DAC_CH_OUTPUT_SCALE_DIV_128))
                                            

/*******************************************************************************
 * ENUMS
 *******************************************************************************/

/**
 * Return types of the API's
 */
typedef enum XMC_DAC_CH_STATUS
{
  XMC_DAC_CH_STATUS_OK              = 0U, /**< Status is ok, no error detected */
  XMC_DAC_CH_STATUS_ERROR           = 1U, /**< Error detected */
  XMC_DAC_CH_STATUS_BUSY            = 2U, /**< DAC is busy */
  XMC_DAC_CH_STATUS_ERROR_FREQ2LOW  = 3U, /**< Frequency can't be configured. Frequency is to low. */
  XMC_DAC_CH_STATUS_ERROR_FREQ2HIGH = 4U  /**< Frequency can't be configured. Frequency is to high.  */
} XMC_DAC_CH_STATUS_t;

/**
 * Operating modes of DAC
 */
typedef enum XMC_DAC_CH_MODE
{
  XMC_DAC_CH_MODE_IDLE    = 0x0U << DAC_DAC0CFG0_MODE_Pos,    /**< DAC is disabled */
  XMC_DAC_CH_MODE_SINGLE  = 0x1U << DAC_DAC0CFG0_MODE_Pos,    /**< Single value mode - single data value is updated and maintained */
  XMC_DAC_CH_MODE_DATA    = 0x2U << DAC_DAC0CFG0_MODE_Pos,    /**< Data mode - continuous data processing */
  XMC_DAC_CH_MODE_PATTERN = 0x3U << DAC_DAC0CFG0_MODE_Pos,    /**< Pattern mode - inbuilt pattern waveform generation -
                                                                   Sine, Triangle, Rectangle */
  XMC_DAC_CH_MODE_NOISE   = 0x4U << DAC_DAC0CFG0_MODE_Pos,    /**< Noise mode - pseudo-random noise generation */
  XMC_DAC_CH_MODE_RAMP    = 0x5U << DAC_DAC0CFG0_MODE_Pos     /**< Ramp mode - ramp generation */
} XMC_DAC_CH_MODE_t;

/**
 * Trigger sources for the data update
 */
typedef enum XMC_DAC_CH_TRIGGER
{
  XMC_DAC_CH_TRIGGER_INTERNAL =
      (0x0U << DAC_DAC0CFG1_TRIGMOD_Pos),                                      /**< Internal trigger as per frequency divider value */
  XMC_DAC_CH_TRIGGER_EXTERNAL_CCU80_SR1 =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | 0x0U,                               /**< External trigger from CCU80 Interrupt SR1 */
  XMC_DAC_CH_TRIGGER_EXTERNAL_CCU40_SR1 =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | (0x2U << DAC_DAC0CFG1_TRIGSEL_Pos), /**< External trigger from CCU40 Interrupt SR1 */
  XMC_DAC_CH_TRIGGER_EXTERNAL_CCU41_SR1 =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | (0x3U << DAC_DAC0CFG1_TRIGSEL_Pos), /**< External trigger from CCU41 Interrupt SR1 */
  XMC_DAC_CH_TRIGGER_EXTERNAL_P2_9 =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | (0x4U << DAC_DAC0CFG1_TRIGSEL_Pos), /**< External trigger from pin 2.9 */
  XMC_DAC_CH_TRIGGER_EXTERNAL_P2_8 =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | (0x5U << DAC_DAC0CFG1_TRIGSEL_Pos), /**< External trigger from pin 2.8 */
  XMC_DAC_CH_TRIGGER_EXTERNAL_U0C0_DX1INS =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | (0x6U << DAC_DAC0CFG1_TRIGSEL_Pos), /**< External trigger from USIC-0 DX1 Input Signal */
  XMC_DAC_CH_TRIGGER_EXTERNAL_U1C0_DX1INS =
      (0x1U << DAC_DAC0CFG1_TRIGMOD_Pos) | (0x7U << DAC_DAC0CFG1_TRIGSEL_Pos), /**< External trigger from USIC-1 DX1 Input Signal */
  XMC_DAC_CH_TRIGGER_SOFTWARE =
      (0x2U << DAC_DAC0CFG1_TRIGMOD_Pos)                                       /**< Software trigger */
} XMC_DAC_CH_TRIGGER_t;

/**
 * Data type of the input data
 */
typedef enum XMC_DAC_CH_DATA_TYPE
{
  XMC_DAC_CH_DATA_TYPE_UNSIGNED = 0U , /**< input data is unsigned */
  XMC_DAC_CH_DATA_TYPE_SIGNED = 1U     /**< input data is signed */
} XMC_DAC_CH_DATA_TYPE_t;

/**
 * Scaling of the input data
 */
typedef enum XMC_DAC_CH_OUTPUT_SCALE
{
  XMC_DAC_CH_OUTPUT_SCALE_NONE =
      0x0U,                                                                   /**< No scaling */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_2 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x1U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 2 */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_4 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x2U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 4 */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_8 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x3U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 8 */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_16 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x4U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 16 */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_32 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x5U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 32 */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_64 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x6U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 64 */
  XMC_DAC_CH_OUTPUT_SCALE_MUL_128 =
      (0x1U << DAC_DAC0CFG1_MULDIV_Pos) | (0x7U << DAC_DAC0CFG1_SCALE_Pos),   /**< multiplied by 128 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_2 =
      0x1U << DAC_DAC0CFG1_SCALE_Pos,                                         /**< divided by 2 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_4 =
      0x2U << DAC_DAC0CFG1_SCALE_Pos,                                         /**< divided by 4 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_8 =
      0x3U << DAC_DAC0CFG1_SCALE_Pos,                                         /**< divided by 8 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_16 =
      0x4U << DAC_DAC0CFG1_SCALE_Pos,                                         /**< divided by 16 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_32 =
      0x5U << DAC_DAC0CFG1_SCALE_Pos,                                         /**< divided by 32 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_64 =
      0x6U << DAC_DAC0CFG1_SCALE_Pos,                                         /**< divided by 64 */
  XMC_DAC_CH_OUTPUT_SCALE_DIV_128 =
      0x7U << DAC_DAC0CFG1_SCALE_Pos                                          /**< divided by 128 */
} XMC_DAC_CH_OUTPUT_SCALE_t;

/**
 * Negation of input data (applicable only for XMC44 device)
 */
typedef enum XMC_DAC_CH_OUTPUT_NEGATION
{
  XMC_DAC_CH_OUTPUT_NEGATION_DISABLED = 0U,                   /**< XMC_DAC_CH_OUTPUT_NEGATION_DISABLED */
  XMC_DAC_CH_OUTPUT_NEGATION_ENABLED = 1U                     /**< XMC_DAC_CH_OUTPUT_NEGATION_ENABLED */
} XMC_DAC_CH_OUTPUT_NEGATION_t;

/**
 * Output sign signal for the Pattern Generation Mode
 */
typedef enum XMC_DAC_CH_PATTERN_SIGN_OUTPUT
{
  XMC_DAC_CH_PATTERN_SIGN_OUTPUT_DISABLED = 0U,  /**< Sign output signal generation is disabled */
  XMC_DAC_CH_PATTERN_SIGN_OUTPUT_ENABLED = 1U    /**< Sign output signal generation is enabled */
} XMC_DAC_CH_PATTERN_SIGN_OUTPUT_t;

/*******************************************************************************
 * DATA STRUCTURES
 *******************************************************************************/
/**
 * DAC peripheral registers configuration.
 */
typedef struct
{
  __I  uint32_t  ID;

  struct
  {
     __IO uint32_t low;
     __IO uint32_t high;
  } DACCFG[XMC_DAC_NO_CHANNELS];

  __IO uint32_t DACDATA[XMC_DAC_NO_CHANNELS];
  __IO uint32_t DAC01DATA;

  struct
  {
     __IO uint32_t low;
     __IO uint32_t high;
  } DACPAT[XMC_DAC_NO_CHANNELS];

} XMC_DAC_t;

/*Anonymous structure/union guard start*/
#if defined(__CC_ARM)
  #pragma push
  #pragma anon_unions
#elif defined(__TASKING__)
  #pragma warning 586
#endif

/**
 * Channel related configuration
 */
typedef struct XMC_DAC_CH_CONFIG
{
  union
  {
  struct
  {
    uint32_t :23;                /**< Not used bits */
    uint32_t data_type:1;        /**< input data type - unsigned / signed */
    uint32_t :4;                 /**< Not used bits */
    uint32_t output_negation:1;  /**< Negation of the output waveform enabled/disabled */
    uint32_t :3;
  };
  uint32_t cfg0;
  };
  union
  {
  struct
  {
    uint32_t output_scale:4;  /**< Scale value of type XMC_DAC_CH_OUTPUT_SCALE_t. It includes scaling + mul/div bit */
    uint32_t output_offset:8; /**< offset value */
    uint32_t :20;
  };
  uint32_t cfg1;
  };
} XMC_DAC_CH_CONFIG_t;
/*Anonymous structure/union guard end*/
#if defined(__CC_ARM)
  #pragma pop
#elif defined(__TASKING__)
  #pragma warning restore
#endif
/*******************************************************************************
 * API PROTOTYPES
 *******************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @param dac Pointer to an instance of DAC module
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enables DAC clock and releases DAC reset.<br>
 *
 * \par
 * Enabling DAC is the first step of DAC initialisation. This API is called by XMC_DAC_CH_Init().
 * DAC clock is enabled by setting \a DAC bit of \a CGATCLR1 register. DAC reset is released by setting \a DACRS bit of \a PRCLR1 register.
 *
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_IsEnabled(), XMC_DAC_Disable(), XMC_DAC_CH_Init()\n\n\n
 *
 */
void XMC_DAC_Enable(XMC_DAC_t *const dac);

/**
 * @param dac Pointer to an instance of DAC module
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disables DAC clock and resets DAC.
 *
 * \par
 * DAC clock is disabled by setting \a DAC bit of \a CGATSET1 register. DAC is reset by setting \a DACRS bit of \a PRSET1 register.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_IsEnabled(), XMC_DAC_Enable()\n\n\n
 *
 */
void XMC_DAC_Disable(XMC_DAC_t *const dac);

/**
 * @param dac Pointer to an instance of DAC module
 *
 * @return bool<br>
 * true  - if DAC is enabled<br>
 * false - if DAC is disabled
 *
 * \par<b>Description:</b><br>
 * Returns the state of the DAC.
 *
 * \par
 * DAC enabled status is determined by referring to \a DACRS bit of \a PRSTAT1 register.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_Enable(), XMC_DAC_Disable()\n\n\n
 *
 */
bool XMC_DAC_IsEnabled(const XMC_DAC_t *const dac);

/**
 * @param dac Pointer to an instance of DAC module
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * DAC switches to Simultaneous data mode from Independent data mode.
 *
 * \par
 * Independent data mode is the default data mode.
 * Simultaneous data mode is enabled by setting \a DATMOD bit of \a DAC0CFG1 register.
 *
 * \par<b>Note:</b><br>
 * Set channel 0 and channel 1 to Data mode before calling this API.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartSingleValueMode(), XMC_DAC_CH_StartDataMode(), XMC_DAC_SimultaneousWrite(), XMC_DAC_DisableSimultaneousDataMode()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_EnableSimultaneousDataMode(XMC_DAC_t *const dac)
{
  XMC_ASSERT("XMC_DAC_EnableSimultaneousDataMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  
  dac->DACCFG[0].high |= DAC_DAC0CFG1_DATMOD_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * DAC switches to independent data mode from simultaneous Data mode.
 *
 * \par
 * Independent data mode is the default data mode.
 * Simultaneous data mode is disabled by clearing \a DATMOD bit of \a DAC0CFG1 register.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartDataMode(), XMC_DAC_EnableSimultaneousDataMode()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_DisableSimultaneousDataMode(XMC_DAC_t *const dac)
{
  XMC_ASSERT("XMC_DAC_DisableSimultaneousDataMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  
  dac->DACCFG[0].high &= ~DAC_DAC0CFG1_DATMOD_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param data0 Data for DAC channel 0 [0-4095]
 * @param data1 Data for DAC channel 1 [0-4095]
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * The data (\e data0 & \e data1) to be converted by channel 0 & channel 1 are updated to \a DATA1 bit-fields of \a DAC01DATA register.
 * data0 and data1 have the range of [0-4095].
 *
 * \par<b>Note:</b><br>
 * Channel 0 and Channel 1 should be set to simultaneous data mode before calling this API.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_EnableSimultaneousDataMode()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_SimultaneousWrite(XMC_DAC_t *const dac, const uint16_t data0, const uint16_t data1)
{
  XMC_ASSERT("XMC_DAC_SimultaneousWrite: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  
  dac->DAC01DATA = (data0 << DAC_DAC01DATA_DATA0_Pos) | (data1 << DAC_DAC01DATA_DATA1_Pos);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param config Pointer to the DAC channel configuration structure
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Initialises and configures the DAC \e channel with the configuration date pointed by \e config.
 *
 * \par
 * DAC channel is initialised by configuring the registers \a DAC0CFG0 and \a DAC0CFG1 registers (for channel 0) / \a DAC1CFG0 and \a DAC1CFG1 registers (for channel 1).
 * It enables the channel output by calling XMC_DAC_CH_EnableOutput().
 *
 */
void XMC_DAC_CH_Init(XMC_DAC_t *const dac, const uint8_t channel, const XMC_DAC_CH_CONFIG_t *const config);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Channel \a channel output is enabled by setting the \a ANAEN bit of \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1).
 *
 * \par<b>Note:</b><BR>
 * \a tSTARTUP time for DAC analog output starts after the \a ANAEN bit is set to one.
 * After the expiry of the startup time the default value is driven to DAC output and a new value can be written.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_DisableOutput(), XMC_DAC_CH_IsOutputEnabled()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_EnableOutput(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_EnableOutput: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_EnableOutput: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  dac->DACCFG[channel].high |= DAC_DAC0CFG1_ANAEN_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Channel \a channel output is disabled by clearing the \a ANAEN bit of \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1).
 *
 * \par
 * A call to this API stops driving the converted digital input to its output.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_EnableOutput(), XMC_DAC_CH_IsOutputEnabled()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_DisableOutput(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_DisableOutput: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_DisableOutput: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  dac->DACCFG[channel].high &= ~DAC_DAC0CFG1_ANAEN_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return bool <BR>
 * true  - if analog output is enabled <BR>
 * false - if analog output is disabled <BR>
 *
 * \par<b>Description:</b><br>
 * Returns the status of DAC analog output.
 *
 * \par
 * Channel \a channel output enabled or disabled is determined by reading the \a ANAEN bit of \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_EnableOutput(), XMC_DAC_CH_DisableOutput()\n\n\n
 *
 */
__STATIC_INLINE bool XMC_DAC_CH_IsOutputEnabled(const XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_IsOutputEnabled: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_IsOutputEnabled: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  return (bool)(dac->DACCFG[channel].high & DAC_DAC0CFG1_ANAEN_Msk);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param data Data to be written  [0-4095]
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Writes the \e data to the \e channel's DATA register.
 *
 * \par
 * The \e data is then converted and driven to the output.
 * If the trigger is set, On a trigger event the data in DATA register is converted and driven to \e channel output.
 * Data \a data is written to the \a channel by loading \a data to \a DATA0 bit-field of \a DAC0DATA (for channel 0) / \a DATA1 bit-field of \a DAC1DATA register (for channel 1).
 * data has the range of [0-4095].
 *
 * \par<b>Note:</b><br>
 * The API can be used for Single Value Mode, Data Mode (Individual) & Ramp Mode.
 * Call XMC_DAC_CH_EnableOutput() API to enable analog output.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartSingleValueMode(), XMC_DAC_CH_StartDataMode(), XMC_DAC_CH_StartRampMode()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_Write(XMC_DAC_t *const dac, const uint8_t channel, const uint16_t data)
{
  XMC_ASSERT("XMC_DAC_CH_Write: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_Write: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  dac->DACDATA[channel] = data;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel to Single Value Mode by calling XMC_DAC_CH_SetMode().
 *
 * \par<b>Note:</b><br>
 * Call XMC_DAC_CH_Write() API to write the data.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_Write()\n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartSingleValueMode(XMC_DAC_t *const dac, const uint8_t channel);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param trigger Data points update trigger
 * @param frequency Waveform frequency [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t status
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel to Data mode. Trigger and frequency are configured.
 *
 * \par<b>Note:</b><br>
 * Call XMC_DAC_CH_Write() API to write the data. Call XMC_DAC_EnableSimultaneousDataMode() to switch to Simultaneous data mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_Init(), XMC_DAC_CH_Write(), XMC_DAC_EnableSimultaneousDataMode() \n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartDataMode(XMC_DAC_t *const dac,
                                             const uint8_t channel,
                                             const XMC_DAC_CH_TRIGGER_t trigger,
                                             const uint32_t frequency);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param start Start point of the ramp [0-4095]
 * @param stop Stop point of the ramp [0-4095]
 * @param trigger Data points update trigger
 * @param frequency Ramp frequency in [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t status
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel to Ramp mode. Trigger, frequency, start and stop values are configured.
 * On a \e trigger ramp values are converted and driven to \e channel output.
 * Start and stop have the range of [0-4095]. Stop should be equal or greater than start. 
 *
 * \par<b>Note:</b><br>
 * If the ramp counter reaches its \e stop value, it restarts from the \e start value with the next trigger pulse.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_Init(), XMC_DAC_CH_GetRampStart(), XMC_DAC_CH_GetRampStop() \n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartRampMode(XMC_DAC_t *const dac,
                                             const uint8_t channel,
                                             const uint16_t start,
                                             const uint16_t stop,
                                             const XMC_DAC_CH_TRIGGER_t trigger,
                                             const uint32_t frequency);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param pattern Data table of a pattern
 * @param sign_output Sign information of the waveform
 * @param trigger Data points update trigger
 * @param frequency Waveform frequency in [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t status
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel to Pattern mode. Trigger, frequency, sign output and data are configured.
 * On a \e trigger, the \e pattern values are converted and driven to \e channel output.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_Init(), XMC_DAC_CH_DisablePatternSignOutput() \n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartPatternMode(XMC_DAC_t *const dac,
                                                const uint8_t channel,
                                                const uint8_t *const pattern,
                                                const XMC_DAC_CH_PATTERN_SIGN_OUTPUT_t sign_output,
                                                const XMC_DAC_CH_TRIGGER_t trigger,
                                                const uint32_t frequency);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param trigger Data points update trigger
 * @param frequency Waveform frequency in [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t status
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel to Noise mode. Trigger and frequency are configured.
 * On a \e trigger the DAC starts converting and drives to \e channel output.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_Init()\n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartNoiseMode(XMC_DAC_t *const dac,
                                              const uint8_t channel,
                                              const XMC_DAC_CH_TRIGGER_t trigger,
                                              const uint32_t frequency);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param pattern Pointer to the data table
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * The data for the Pattern mode is written to the \a DAC0PATL and \a DAC0PATH registers.
 * The API is called by XMC_DAC_CH_StartPatternMode().
 *
 * \par<b>Note:</b><br>
 * Call this API if the \a channel is set to Pattern mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_EnablePatternSignOutput(), XMC_DAC_CH_DisablePatternSignOutput()\n\n\n
 *
 */
void XMC_DAC_CH_SetPattern(XMC_DAC_t *const dac, const uint8_t channel, const uint8_t *const pattern);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enables the output sign information for Pattern Mode.
 *
 * \par
 * Sign output is enabled by setting \a SIGNEN bit of \a DAC0CFG0 register (for channel 0) / DAC1CFG0 register (for channel 1).
 *
 * \par<b>Note:</b><br>
 * Call this API if the \e channel is set to Pattern mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartPatternMode(), XMC_DAC_CH_DisablePatternSignOutput()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_EnablePatternSignOutput(XMC_DAC_t *const dac,
                                                     const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_EnablePatternSignOutput: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_EnablePatternSignOutput: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  dac->DACCFG[channel].low |= DAC_DAC0CFG0_SIGNEN_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disables output sign information for Pattern Mode.
 *
 * \par
 * Sign output is disabled by clearing \a SIGNEN bit of \a DAC0CFG0 register (for channel 0) / DAC1CFG0 register (for channel 1).
 *
 * \par<b>Note:</b><br>
 * Call this API if the \e channel is set to Pattern mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartPatternMode(), XMC_DAC_CH_EnablePatternSignOutput()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_DisablePatternSignOutput(XMC_DAC_t *const dac,
                                                     const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_DisablePatternSignOutput: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_DisablePatternSignOutput: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  dac->DACCFG[channel].low &= ~DAC_DAC0CFG0_SIGNEN_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param start Ramp start point [0-4095]
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the ramp start value by writing to the register \a DAC0DATA (for \e channel 0) or \a DAC1DATA (for \e channel 1).
 * If the ramp counter reaches its stop value, it restarts from the \a start value with the next trigger pulse.
 * Ensure \e start value is lower than the stop value.
 *
 * \par<b>Note:</b><br>
 * Call this API if the \a channel is set to Ramp mode.
 * Start value is a 12 bit data.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_GetRampStart(), XMC_DAC_CH_GetRampStop(), XMC_DAC_CH_SetRampStop()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetRampStart(XMC_DAC_t *const dac, const uint8_t channel, const uint16_t start)
{
  XMC_ASSERT("XMC_DAC_CH_SetRampStart: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetRampStart: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  dac->DACDATA[channel] = start;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return uint16_t
 *
 * \par<b>Description:</b><br>
 * Gets the ramp start value by reading \a DATA0 bit-field of \a DAC0DATA register (for channel 0) / \a DATA1 bit-field of \a DAC1DATA register (for channel 1).
 * If the ramp counter reaches its stop value, it restarts from the start value with the next trigger pulse.
 *
 * \par<b>Note:</b><br>
 * Call this API if the \e channel is set to Ramp mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetRampStart(), XMC_DAC_CH_StartRampMode(), XMC_DAC_CH_GetRampStop(), XMC_DAC_CH_SetRampStop()\n\n\n
 *
 */
__STATIC_INLINE uint16_t XMC_DAC_CH_GetRampStart(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_GetRampStart: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_GetRampStart: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  
  return (uint16_t)(dac->DACDATA[channel]);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param stop Ramp stop point [0-4095]
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the ramp stop value by writing to the bit-field \a DATA0 (for \e channel 0) or \a DATA1 (for \e channel 1) of \a DAC01DATA register.
 * If the ramp counter reaches its \a stop value, it restarts from the start value with the next trigger pulse.
 * Ensure \e stop value is higher than the start value.
 *
 * \par<b>Note:</b><br>
 * Call this API if the \e channel is set to Ramp mode.
 * Stop value is a 12 bit data.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_GetRampStop(), XMC_DAC_CH_SetRampStart()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetRampStop(XMC_DAC_t *const dac, const uint8_t channel, const uint16_t stop)
{
  XMC_ASSERT("XMC_DAC_CH_SetRampStop: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetRampStop: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DAC01DATA = (dac->DAC01DATA & ~(DAC_DAC01DATA_DATA0_Msk << (channel * DAC_DAC01DATA_DATA1_Pos))) |
               (stop << (channel * DAC_DAC01DATA_DATA1_Pos));
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return uint16_t
 *
 * \par<b>Description:</b><br>
 * Gets the ramp stop value by reading \a DATA0 bit-field of \a DAC01DATA register (for channel 0) / \a DATA1 bit-field of \a DAC01DATA register (for channel 1).
 * If the ramp counter reaches its stop value, it restarts from the start value with the next trigger pulse.
 *
 * \par<b>Note:</b><br>
 * Call this API if the \e channel is set to Ramp mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetRampStop(), XMC_DAC_CH_StartRampMode(), XMC_DAC_CH_GetRampStart()\n\n\n
 *
 */
__STATIC_INLINE uint16_t XMC_DAC_CH_GetRampStop(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_GetRampStop: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_GetRampStop: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));

  return((dac->DAC01DATA >> (channel * DAC_DAC01DATA_DATA1_Pos)) & DAC_DAC01DATA_DATA0_Msk);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param trigger Trigger source
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Selects the \e trigger source for the \e channel by configuring the bits TRIGSEL & TRIGMOD of CFG register.
 *
 * \par
 * Channel \a channel trigger source is selected by \a TRIGSEL bit-field of \a DAC0CFG1 register (for channel 0) / DAC1CFG1 register(for channel 1).
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetTrigger(XMC_DAC_t *const dac, const uint8_t channel, const XMC_DAC_CH_TRIGGER_t trigger)
{
  XMC_ASSERT("XMC_DAC_CH_SetTrigger: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetTrigger: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  XMC_ASSERT("XMC_DAC_CH_SetTrigger: trigger parameter not valid\n", XMC_DAC_IS_TRIGGER_VALID(trigger));

  dac->DACCFG[channel].high = (dac->DACCFG[channel].high & ~(DAC_DAC0CFG1_TRIGSEL_Msk | DAC_DAC0CFG1_TRIGMOD_Msk)) |
                              trigger;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param frequency Waveform frequency in [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t
 *
 * \par<b>Description:</b><br>
 * Sets the \e frequency of DAC channel.
 *
 * \par
 * The value \e frequency acts as clock divider. The smallest \e frequency divider value is 16.
 * A valid \e frequency value should be within the range XMC_DAC_MIN_FREQ_DIVIDER to XMC_DAC_MAX_FREQ_DIVIDER. A value outside this range is considered as in valid and API returns error.
 * Frequency \a frequency is configured by setting \a FREQ bit-field of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 *
 * \par<b>Note:</b><br>
 * Call this API only for Single value mode, Data mode and Noise mode.
 * Call XMC_DAC_CH_SetRampFrequency() in case of Ramp mode and XMC_DAC_CH_SetPatternFrequency() in case of Pattern mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetRampFrequency(), XMC_DAC_CH_SetPatternFrequency()\n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_SetFrequency(XMC_DAC_t *const dac, const uint8_t channel, const uint32_t frequency);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param frequency [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t
 *
 * \par<b>Description:</b><br>
 * Sets the \e frequency of DAC channel by calling XMC_DAC_CH_SetFrequency().
 *
 * \par
 * For the Ramp mode, the \a frequency of operation depends on the total number of sample points (\a stop - \a start).
 * Frequency \e frequency is multiplied by the total number of sample points, so that each trigger instance converts all the sample points of ramp.
 *
 * \par<b>Note:</b><br>
 * Call this API only if the \a channel is set to Ramp mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartRampMode()\n\n\n
 *
 */
XMC_DAC_CH_STATUS_t XMC_DAC_CH_SetRampFrequency(XMC_DAC_t *const dac, const uint8_t channel, const uint32_t frequency);

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param frequency in [Hz]
 *
 * @return XMC_DAC_CH_STATUS_t
 *
 * \par<b>Description:</b><br>
 * Sets the \e frequency of DAC channel by calling XMC_DAC_CH_SetFrequency().
 *
 * \par
 * For the Pattern mode, the \a frequency of operation depends on the total number of sample points \a XMC_DAC_SAMPLES_PER_PERIOD.
 * Frequency \e frequency is multiplied by the total number of sample points, so that each trigger instance converts all the sample points of the pattern.
 *
 * \par<b>Note:</b><br>
 * Call this API only if the \a channel is set to Pattern mode.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_StartPatternMode()\n\n\n
 *
 */
__STATIC_INLINE XMC_DAC_CH_STATUS_t XMC_DAC_CH_SetPatternFrequency(XMC_DAC_t *const dac,
                                                                   const uint8_t channel,
                                                                   const uint32_t frequency)
{
  XMC_ASSERT("XMC_DAC_CH_SetPatternFrequency: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetPatternFrequency: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));

  return XMC_DAC_CH_SetFrequency(dac, channel, frequency * XMC_DAC_SAMPLES_PER_PERIOD);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param mode DAC operation mode
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the operating \e mode for the \e channel by setting the \a MODE bit-field of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 * Different modes of DAC operation are defined by enum XMC_DAC_CH_MODE_t.
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetMode(XMC_DAC_t *const dac, const uint8_t channel, const XMC_DAC_CH_MODE_t mode)
{
  XMC_ASSERT("XMC_DAC_CH_SetMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetMode: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  XMC_ASSERT("XMC_DAC_CH_SetMode: trigger parameter not valid\n", XMC_DAC_IS_MODE_VALID(mode));
    
  dac->DACCFG[channel].low = (dac->DACCFG[channel].low & ~DAC_DAC0CFG0_MODE_Msk) |
                             mode;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel's data to signed type by setting \a SIGN bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 * The data for the conversion would then be treated as signed data type.
 *
 * \par<b>Note:</b><br>
 * Offset and scaling can be applied to the data by calling XMC_DAC_CH_SetOutputOffset(), XMC_DAC_CH_SetOutputScale().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetUnsignedDataType()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetSignedDataType(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_SetSignedDataType: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetSignedDataType: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].low |= (DAC_DAC0CFG0_SIGN_Msk);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the \e channel's data to unsigned type by clearing \a SIGN bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 * The data for the conversion would then be treated as unsigned data type.
 *
 * \par<b>Note:</b><br>
 * Offset and scaling can be applied to the data by calling XMC_DAC_CH_SetOutputOffset(), XMC_DAC_CH_SetOutputScale().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetSignedDataType()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetUnsignedDataType(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_SetUnsignedDataType: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetUnsignedDataType: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].low &= ~(DAC_DAC0CFG0_SIGN_Msk);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * A call to this API generates a trigger pulse by setting \a SWTRIG bit of \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1),
 * provided the \a TRIGMOD bit of CFG register is set to \a XMC_DAC_CH_TRIGGER_SOFTWARE.
 *
 * \par<b>Note:</b><br>
 * If the \e channel is set to simultaneous data mode, SWTRIG bit of \e channel 1 is not valid.
 * Only \a SWTRIG bit of channel 0 is used for channel 1.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetTrigger(), XMC_DAC_CH_EnableEvent()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SoftwareTrigger(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_SoftwareTrigger: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SoftwareTrigger: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].high |= DAC_DAC0CFG1_SWTRIG_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enables service request by setting \a SREN bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 * Trigger signal is generated upon conversion of each data.
 *
 * \par<b>Note:</b><br>
 * The service request signal can be connected to NVIC, DMA.\n
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_DisableEvent()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_EnableEvent(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_EnableEvent: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_EnableEvent: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].low |= DAC_DAC0CFG0_SREN_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disables service request by clearing \a SREN bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_EnableEvent()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_DisableEvent(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_DisableEvent: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_DisableEvent: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].low &= ~DAC_DAC0CFG0_SREN_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param offset
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Sets the offset value.\n
 * Offset range:0 - 255\n
 * interpreted as : -128 to 127 (twos complement) in signed mode and 0 to 255 in unsigned mode.
 *
 * \par<b>Note:</b><br>
 * Scaling can be applied to the output data after adding the \e offset value.
 *
 * \par
 * Channel \a channel \a offset value is loaded to the bit-field \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetOutputScale()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetOutputOffset(XMC_DAC_t *const dac, const uint8_t channel, const uint8_t offset)
{
  XMC_ASSERT("XMC_DAC_CH_SetOutputOffset: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetOutputOffset: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].high = (dac->DACCFG[channel].high & ~DAC_DAC0CFG1_OFFS_Msk) |
                              offset << DAC_DAC0CFG1_OFFS_Pos;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 * @param scale Input data scaling
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Data of the \e channel is scaled.
 *
 * \par
 * The data can either be scaled up-scaled (multiplied), down-scaled (divided) or no scaling (as is) based on the value of \e scale.
 * Scaling is configured by setting bit-fields \a MULDIV and \a SCALE of \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_GetOutputScale()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_SetOutputScale(XMC_DAC_t *const dac, const uint8_t channel, const XMC_DAC_CH_OUTPUT_SCALE_t scale)
{
  XMC_ASSERT("XMC_DAC_CH_SetOutputScale: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_SetOutputScale: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
  XMC_ASSERT("XMC_DAC_CH_SetOutputScale: scale parameter not valid\n", XMC_DAC_IS_OUTPUT_SCALE_VALID(scale));

  dac->DACCFG[channel].high = (dac->DACCFG[channel].high & ~(DAC_DAC0CFG1_MULDIV_Msk | DAC_DAC0CFG1_SCALE_Msk)) |
                              scale;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return XMC_DAC_CH_OUTPUT_SCALE_t
 *
 * \par<b>Description:</b><br>
 * Returns scaling information for the data.
 * The input data could be either up-scaled (multiplied), down-scaled (divided) or without scaling (as is).\n
 * Scaling factor is determined by reading bit-fields \a MULDIV and \a SCALE of \a DAC0CFG1 register (for channel 0) / \a DAC1CFG1 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_SetOutputScale()\n\n\n
 *
 */
__STATIC_INLINE XMC_DAC_CH_OUTPUT_SCALE_t XMC_DAC_CH_GetOutputScale(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_GetOutputScale: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_GetOutputScale: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  return (XMC_DAC_CH_OUTPUT_SCALE_t)(dac->DACCFG[channel].high & (DAC_DAC0CFG1_MULDIV_Msk | DAC_DAC0CFG1_SCALE_Msk));
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * \par<b>Description:</b><br>
 * Enables output negation.
 *
 * \par
 * By negating the DAC value is converted to its two's complement values.
 * Can be used in Ramp mode to generate negative ramp.
 * Negation in enabled by setting \a NEGATE bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 *
 * \par<b>Note:</b><br>
 * Negation feature is not applicable for XMC45 devices. Calling this API in XMC45 devices doesn't have any effect.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_DisableOutputNegation(), XMC_DAC_CH_StartRampMode()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_EnableOutputNegation(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_EnableOutputNegation: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_EnableOutputNegation: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].low |= XMC_DAC_DACCFG_NEGATE_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * \par<b>Description:</b><br>
 * Disables output negation.
 *
 * \par
 * Negation is disabled by clearing \a NEGATE bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 *
 * \par<b>Note:</b><br>
 * Negation feature is not applicable for XMC45 devices. Calling this API in XMC45 devices doesn't have any effect.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_EnableOutputNegation()\n\n\n
 *
 */
__STATIC_INLINE void XMC_DAC_CH_DisableOutputNegation(XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_DisableOutputNegation: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_DisableOutputNegation: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  dac->DACCFG[channel].low &= ~XMC_DAC_DACCFG_NEGATE_Msk;
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return bool\n
 * true  - if FIFO is full\n
 * false - if FIFO is not full
 *
 * \par<b>Description:</b><br>
 * Returns FIFO status.\n
 *
 * \par
 * FIFIO full status is determined by reading \a FIFOFUL bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_IsFifoEmpty()\n\n\n
 *
 */
__STATIC_INLINE bool XMC_DAC_CH_IsFifoFull(const XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_IsFifoFull: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_IsFifoFull: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  return (bool)(dac->DACCFG[channel].low & DAC_DAC0CFG0_FIFOFUL_Msk);
}

/**
 * @param dac Pointer to an instance of DAC module
 * @param channel DAC channel number
 *
 * @return bool\n
 * true  - if FIFO is empty\n
 * false - if FIFO is not empty
 *
 * \par<b>Description:</b><br>
 * Returns FIFO status.
 *
 * \par
 * FIFIO empty status is determined by reading \a FIFOEMP bit of \a DAC0CFG0 register (for channel 0) / \a DAC1CFG0 register (for channel 1).
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_DAC_CH_IsFifoFull()\n\n\n
 *
 */
__STATIC_INLINE bool XMC_DAC_CH_IsFifoEmpty(const XMC_DAC_t *const dac, const uint8_t channel)
{
  XMC_ASSERT("XMC_DAC_CH_IsFifoEmpty: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
  XMC_ASSERT("XMC_DAC_CH_IsFifoEmpty: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
    
  return (bool)(dac->DACCFG[channel].low & DAC_DAC0CFG0_FIFOEMP_Msk);
}

#ifdef __cplusplus
}
#endif

/**
 * @}
 */

/**
 * @}
 */

#endif /* defined(DAC) */

#endif /* XMC_DAC_H */
